﻿

using Dapper;
using HBase;
using Net.http;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;

namespace hCommand
{
    /**
   *┌────────────────────────────────────────────────┐
   *│　描    述：Component                                                    
   *│　作    者：sgj                                              
   *│　版    本：1.0                                              
   *│　创建时间：2020/9/2 11:28:16                        
   *└────────────────────────────────────────────────┘
   **/
    public class InAreaGroupEngine<CS> : AbsTaskEngine where CS : AbsCoreStock  {
        public String boxCode;
        public int stn;


        protected long itemClassifyId;
        protected long goodDiff;
   

        List<long> areaList;
        List<CoreWhGroupStat> hisDiffList;
        MyDict<int ,double> craneTasks;

        MyDict<long ,int> priorityDict;



        private bool priority2 = false;//平均库位存放
        private bool priority3 = false;//垛机间入库最快
        void continueTask(IDbConnection conn ,IDbTransaction trans ,CoreTask ct) {


            String sql = "select * from Core_task_param where task_id=@taskId  and type={0} and status < {1} and status>{2} ";
            sql = String.Format(sql ,( int ) TaskParamType.托盘搬运 ,( int ) CoreTaskParamStatus.执行完成 ,( int ) CoreTaskParamStatus.删除);

            List<CoreTaskParam> list = conn.Query<CoreTaskParam>(sql ,new { taskId = ct.id } ,trans).ToList();
            if( list.Count > 0 ) {
                return;
            }
            CS cs = conn.GetById<CS>(ct.stockId ,trans);
            if( cs.status == ( int ) StockStatus.盘库中 ) {
                moveCoreTaskParam(conn ,trans ,"" ,ct.id ,stn ,ct.src ,"");
            }
        }
        protected override TransRes Execute(IDbConnection conn ,IDbTransaction tran) {
            List<CoreTask> coreTaskList = checkCodeInWork(conn ,tran);
            if( coreTaskList.Count == 1 ) {
                continueTask(conn ,tran ,coreTaskList[0]);
                return new TransRes();
            } else if( coreTaskList.Count > 1 ) {

                return new TransRes(true ,boxCode + "at" + stn + "working 不能入库!");
            }
            before(conn ,tran);
            CS cs = getStock(conn, tran);

            if ( cs.status != ( int ) StockStatus.库外 ) {
                return new TransRes(boxCode + "at" + stn + "状态不能入库!" + cs.status);
            }
            // 可能原来入库站台，与正式入库口不一直。
            cs.locId = stn;
            long stockId = cs.id;


       
            long goodDiff = cs.deepDiff;
            int des = getDes(conn, tran, cs);
            if (des == 0) {
                return new TransRes("货位获取异常");
            }
            createInTask(goodDiff ,cs , des, conn ,tran);
           
            return afterIntask(conn ,tran ,cs );
        }

      int  getDes(IDbConnection conn, IDbTransaction tran, CS cs) {
            AbsCoreWhPos group = selectGroup(conn, tran, cs);
            if (group == null) {
                return 0 ;
            }
            return (int)group.id;
        }


        protected virtual TransRes afterIntask(IDbConnection conn ,IDbTransaction trans ,CS cs ) {
            return new TransRes();
        }
        protected virtual void before(IDbConnection connection ,IDbTransaction transaction) {
        }

        protected virtual List<CoreTask> checkCodeInWork(IDbConnection connection ,IDbTransaction transaction) {
            string sql = "select * from Core_Task where  status <9 and  status>0 ";

            if( !String.IsNullOrWhiteSpace(boxCode) ) {
                sql += "  and box_Code=@boxCode  ";
            } else {
                sql += "  and src =  " + stn;
            }
            List<CoreTask> coreTaskList = connection.Query<CoreTask>(sql ,new {
                boxCode
            } ,transaction).ToList();
            return coreTaskList;
        }

        public virtual CS getStock(IDbConnection Connection ,IDbTransaction transaction) {
            string sql = @"select * from Core_stock where  status in (0,1,2,3,4,5,6,7)   and box_Code=@boxCode  ";
            List<CS> stockList = Connection.Query<CS>(sql ,new {
                boxCode
            } ,transaction).ToList();
            ;
            if( stockList.Count == 0 ) {
                String info = boxCode + "没有库位异常stock!";
                throw new Exception(info);
            }
            if( stockList.Count > 1 ) {
                String info = boxCode + "重复的库位异常stock!";
                throw new Exception(info);
            }
            CS cs = stockList[0];
            return cs;
        }




        void init(IDbConnection conn ,IDbTransaction trans ,long itemClassifyId) {
          
            if( itemClassifyId == 0 ) {
                throw new Exception(itemClassifyId + "的分类未找到");
            }
            List<CoreClassifyArea> coreClassifyAreaList =loadCoreClassifyArea(itemClassifyId ,conn ,trans);
      

            priorityDict = new MyDict<long ,int>();
            areaList = new List<long>();
            for( int j = 0;j < coreClassifyAreaList.Count;j++ ) {
                CoreClassifyArea areaDto = coreClassifyAreaList[j];
                if( areaDto.priority == 2 ) {
                    priority2 = true;
                } else if( areaDto.priority == 3 ) {
                    priority3 = true;
                }
                priorityDict.addOverride(areaDto.areaId ,areaDto.priority);
                areaList.Add(areaDto.areaId);
            }
            if( priority2 ) {
                String diff = "SELECT * FROM core_wh_group_stat where diff_key=@goodDiff";
                hisDiffList = conn.Query<CoreWhGroupStat>(diff ,new { goodDiff } ,trans).ToList();
            }
            if( priority3 ) {
                craneTasks = getCraneWork(conn ,trans);
            }
        }
        virtual protected AbsCoreWhPos selectGroup(IDbConnection conn ,IDbTransaction trans ,CS cs) {
            init(conn ,trans , cs.classifyId);


            String groupSql = "SELECT * FROM core_wh_group  where area_id in @areaList and max_stock>count_stock and wcs_auto_active=1";
            List<CoreWhGroup> groups = conn.Query<CoreWhGroup>(groupSql ,new { areaList = areaList.ToArray() } ,trans).ToList();
            double weight = 0;
            CoreWhGroup group = null;
            foreach( var g in groups ) {
                int priority = priorityDict.getValue(g.areaId);
                long areaId = g.areaId;
                if( group != null && isFull(group) ) {
                    continue;
                }
                if (priority == 1) {//优先
                    group = g;
                    break;//起到优化作用，减少无意义循环
                } else {
                    var w = 0.0;
                    if (priority == 2) {//平均
                         w = 1 - getPriority2Per(group, areaId); 
                    } else if (priority == 3) {//总体入库最快
                         w = 1 - craneTasks.getValue(g.craneId); 
                    }
                    if (w >= weight) {
                        group = g;
                        weight = w;
                    }
                }
                weight = locChangeWeight(itemClassifyId ,goodDiff ,weight);
            }
            return group;
        }

        double getPriority2Per(CoreWhGroup group ,long areaId) {
            float count = 0;
            foreach( CoreWhGroupStat diff in hisDiffList ) {
                if( diff.areaId == areaId && diff.groupId == group.locGroup ) {
                    count += diff.countStock;
                }
            }
            float all = count + group.maxStock - group.countStock;
            return count / all;
        }
        List<CoreClassifyArea> loadCoreClassifyArea(long itemClassifyId ,IDbConnection conn ,IDbTransaction trans) {
            string sql = @"select * from core_classify_Area  where classify_Id=@classifyId order by Priority ";
            //一个物料类别对应多个区域 查询物料优先放在哪个区域
            List<CoreClassifyArea> coreClassifyAreaList = conn.Query<CoreClassifyArea>(sql ,new {
                classifyId = itemClassifyId
            } ,trans).ToList();
            return coreClassifyAreaList;
        }
        MyDict<int ,double> getCraneWork(IDbConnection conn ,IDbTransaction trans) {
            String sql = @" SELECT crane_Id, sum(count_in) count_in ,  sum(count_ining) count_ining ,
                        sum(count_outin) count_outin ,sum(count_out) count_out FROM core_wh_group GROUP BY crane_Id ";
            List<CoreWhGroup> all = conn.Query<CoreWhGroup>(sql ,null ,trans).ToList();
            double sum = 1;
            foreach( CoreWhGroup g in all ) {
                sum += g.countIn + g.countOut + g.countOutin + g.countIning;
            }
            MyDict<int ,double> res = new MyDict<int ,double>();

            foreach( CoreWhGroup g in all ) {
                res.addOverride(g.craneId ,(g.countIn + g.countOut + g.countOutin + g.countIning) / sum);

            }
            return res;
        }


        protected virtual double locChangeWeight(long itemClassifyId ,long group ,double weight) {
            return weight;
        }
        protected virtual bool isFull(CoreWhGroup item) {
            return item.maxStock <= item.countStock + 1;
        }

        protected virtual long getGroup(IDbConnection connection ,IDbTransaction transaction ,long itemId) {
            return itemId;

        }
    }
}
